/*
 * File:   kompartir.c
 * Author: Subhabrata
 *
 * Created on August 12, 2010, 1:15 AM
 */

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<netdb.h>
#include<termios.h>
#include<unistd.h>
#include<sys/wait.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<arpa/inet.h>
#include<netinet/in.h>

/* Global Variables*/
int socketFD,newSockFD,sockFD;

/* Function Protypes */
void socketMain(char *port);
void clientMain(int portNo, char *ip);


/**
 *      -------Main Function-----
 *      @author    Subhabrata
 *
 **/
int main()
{

      char *portNo="4040",*ip="10.106.8.101"; // ip of the server
      int status;
      pid_t pid;
      printf("Press Ctrl+D to close the program..\n\n\n");
      pid = fork();
      if (pid == 0)
      {
          socketMain(portNo);  /* This is the child process.  Execute the shell command. */
      }
      else if (pid < 0)
            status = -1;  /* The fork failed.  Report failure.  */
            else
      {
      while(1)    /* This is the parent process.  Wait for the child to complete.  */
      {
            clientMain(atoi(portNo),ip);
      }
      return 0;
      }
      return status;
}



/**
 *      @author         Subhabrata
 *      @param  *msg     print the msg as prefix followed by a colon to the standard error
 **/
void error(char *msg)
{
    perror(msg);
    exit(1);
}


/**
 *      @author         Subhabrata
 *      @param  *port   port  the portno of the server socket
 **/
void socketMain(char *port)
{
     int  portno, clilen,n;
     char buffer[256];
     struct sockaddr_in servAddr, cliAddr;
     pid_t pid;

     sockFD = socket(AF_INET, SOCK_STREAM, 0);
     if (sockFD < 0)
     {
        close(sockFD);
        error("ERROR opening socket");
     }

     bzero((char *) &servAddr, sizeof(servAddr));
     portno = atoi(port);
     servAddr.sin_family = AF_INET;
     inet_pton(AF_INET, "10.106.8.100", &(servAddr.sin_addr));// my ip
     servAddr.sin_port = htons(portno);

     if (bind(sockFD, (struct sockaddr *) &servAddr,sizeof(servAddr)) < 0)
     {

         int on = 1;
         if (setsockopt(sockFD, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) < 0)
         {
                close(sockFD);
                error("setsockopt(SO_REUSEADDR) failed");
         }
        
     }
    

     listen(sockFD,5);
     clilen = sizeof(cliAddr);

     

     while (1)
     {

 	newSockFD = accept(sockFD,(struct sockaddr *) &cliAddr,(socklen_t *)&clilen);

 	if (newSockFD < 0)
            error("ERROR on accept");
   	pid = fork();
   	if (pid < 0)
            error("ERROR on fork");
   	if (pid == 0)
   	{
            bzero(buffer,256);
            n = read(newSockFD,buffer,255);
            if (n < 0)
                error("ERROR reading from socket");

            printf("Message: %s\n",buffer);
            close(newSockFD);
            exit(0);
        }
        else
            close(newSockFD);
     }
    close(sockFD);
}


/**
 *      @author         Subhabrata
 *      @param  portno  port  the portno of the server
 *      @param  *ip     ip address of the server
 **/
void clientMain(int portNo, char *ip)
{
    char buffer[256];
    int n=0,ch;
    struct sockaddr_in clientService;

    socketFD = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
    if (-1 == socketFD)
    {
      perror("cannot create socket");
      exit(EXIT_FAILURE);
    }

    clientService.sin_family = AF_INET;
    clientService.sin_addr.s_addr = inet_addr( ip );
    clientService.sin_port = htons( portNo );
    if (-1 == connect(socketFD,(struct sockaddr *)&clientService,sizeof(clientService)))
    {
      error("connect failed");
      close(socketFD);
      exit(EXIT_FAILURE);
    }

    printf("\nPlease enter the message: ");
    bzero(buffer,256);
    n=0;
    ch='\0';
    while(ch !='\n')
    {
        if((ch= getc( stdin )) == EOF)
        {   printf("\nExiting...\n");
            shutdown(sockFD,SHUT_RDWR);
            shutdown(newSockFD,SHUT_RDWR);
            shutdown(socketFD,SHUT_RDWR);
            exit(0);
        }
        buffer[n]=ch;
        n++;
    }
    n = write(socketFD,buffer,strlen(buffer));
    if (n < 0)
    {
         close(socketFD);
         error("ERROR writing to socket");
    }
    close(socketFD);
}

